using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using Common = Microsoft.ConnectionEngine.Registers.Health.Patient.Common;
using DataAccess = Microsoft.ConnectionEngine.Registers.Health.Patient.DataAccess;
using Microsoft.ConnectionEngine.Registers.Health.Patient.Common;

namespace Microsoft.ConnectionEngine.Registers.Health.Patient.Business
{
    public class PatientManager
    {

        #region Updates/Inserts

        /// <summary>
        /// Update an existing patient
        /// </summary>
        /// <param name="patient">An object representation of the patient being updated.</param>
        /// <param name="userID">The unique identifier of the user updating the patient.</param>
        /// <returns>Returns a boolean indicating the success of the operation</returns>
        public static bool Update(Common.Patient patient, string userID)
        {
            patient.ValidatePatient();

            // return error if object is not already checked out to provider
            if (!DataAccess.Patient.IsLocked(patient.PatientID, userID))
            {
                throw new Exception("Patient Not Locked by user");

            }

            //using (TransactionScope scope = new TransactionScope())
            //{


                // try to update
                DataAccess.Patient.PatientUpdate(patient.PatientID,
                                                    patient.DonorFlag,
                                                    patient.AddressLine1,
                                                    patient.AddressLine2,
                                                    patient.AddressSuburb,
                                                    patient.AddressTownCity,
                                                    patient.AddressCountry,
                                                    patient.AddressCode,
                                                    userID);

                DataAccess.Person.PersonUpdate(patient.PatientID,
                                                    patient.DateOfBirth,
                                                    patient.DateOfDeath,
                                                    patient.Gender,
                                                    userID);


                foreach (Common.Name name in patient.Names)
                {
                    if (name.Status != NameStatus.none)
                    {
                        DataAccess.PersonName.PersonNameInsert(patient.PatientID,
                            name.PrimaryAlias,
                            name.Title,
                            name.FamilyName,
                            name.GivenName1,
                            name.GivenName2,
                            name.GivenName3,
                            userID,
                            name.PreferredGivenNameIndex);
                    }
                //}


                //scope.Complete();
            }

            return true;

        }


        /// <summary>
        /// Insert an new patient
        /// </summary>
        /// <param name="patient">An object representation of the patient being inserted.</param>
        /// <param name="userID">The unique identifier of the user inserting the new patient.</param>
        /// <returns>Returns a boolean indicating the success of the operation</returns>
        public static bool Insert(Common.Patient patient, string userID)
        {
            patient.ValidatePatient();

            //using (TransactionScope scope = new TransactionScope())
            //{

                int iPersonID = DataAccess.Person.PersonInsert(patient.DateOfBirth,
                                                    patient.DateOfDeath,
                                                    patient.Gender,
                                                    userID);

                patient.PatientID = DataAccess.Patient.PatientInsert(patient.PatientID,
                                                    iPersonID,
                                                    patient.DonorFlag,
                                                    patient.AddressLine1,
                                                    patient.AddressLine2,
                                                    patient.AddressSuburb,
                                                    patient.AddressTownCity,
                                                    patient.AddressCountry,
                                                    patient.AddressCode,
                                                    userID);

                foreach (Common.Name name in patient.Names)
                {
                        DataAccess.PersonName.PersonNameInsert(patient.PatientID,
                            name.PrimaryAlias,
                            name.Title,
                            name.FamilyName,
                            name.GivenName1,
                            name.GivenName2,
                            name.GivenName3,
                            userID,
                            name.PreferredGivenNameIndex);
                }

            //    scope.Complete();
            //}

            return true;
        }

        #endregion

        #region Selects/Searches

        /// <summary>
        /// Selects a patient based on their unique identifier
        /// </summary>
        /// <param name="patientID">The unique identifier of the patient being selected.</param>
        /// <param name="userID">The unique identifier of the user selecting the patient.</param>
        /// <returns>Returns an object representation of the selected patient.</returns>
        public static Common.Patient Select(string patientID, string userID)
        {
            Common.DataSets.dsPatient dPatient = DataAccess.Patient.PatientSelect(patientID);
            
            return new Common.Patient(dPatient,0);
        }

        /// <summary>
        /// Searches for patients based on a search criteria.
        /// </summary>
        /// <param name="sRequest">An object representation of the search criteria.</param>
        /// <param name="userID">The unique identifier of the user searching for patients.</param>
        /// <returns>Returns a list of patients matching the search criteria.</returns>
        public static Common.Patients Search(Common.SearchRequest sRequest, string userID)
        {
            Common.DataSets.dsPatient dPatient = DataAccess.Patient.PatientSearch(sRequest.PatientID,
                sRequest.AddressLine1,
                sRequest.AddressTownCity,
                sRequest.AddressCountry,
                sRequest.AddressCode,
                sRequest.Title,
                sRequest.FamilyName,
                sRequest.GivenName1,
                sRequest.GivenName2,
                sRequest.GivenName3,
                sRequest.DateOfBirth,
                sRequest.DateOfDeath,
                sRequest.Gender);

            Common.Patients patReturn = new Common.Patients();

            for (int x = 0; x < dPatient.Patient.Count; x++)
            {
                patReturn.Items.Add(new Common.Patient(dPatient, x));
            }

            return patReturn;
        }



        #endregion

        #region Locking

        /// <summary>
        /// Locks a patient record for edit.
        /// </summary>
        /// <param name="patientID">The unique identifier of the patient being locked.</param>
        /// <param name="userID">The unique identifier of the user locking the patient.</param>
        /// <returns>Returns a boolean representing the succcess of the operation.</returns>
        public static bool Lock(string patientID, string userID)
        {
            return DataAccess.Patient.PatientLock(patientID, userID);
        }
        /// <summary>
        /// Unlocks a patient record.
        /// </summary>
        /// <param name="patientID">The unique identifier of the patient being unlocked.</param>
        /// <param name="userID">The unique identifier of the user unlocking the patient.</param>
        /// <returns>Returns a boolean representing the succcess of the operation.</returns>
        public static bool Unlock(string patientID, string userID)
        {
            return DataAccess.Patient.PatientUnlock(patientID, userID);
        }

        /// <summary>
        /// Unlock all patient records associated to a user.
        /// </summary>
        /// <param name="userID">The unique identifier of the user requesting the unlock.</param>
        /// <returns>Returns a boolean representing the succcess of the operation.</returns>
        public static bool UnlockAll(string userID)
        {
            return DataAccess.Patient.PatientUnlockAll(userID);
        }


        #endregion 

    }
}
